"""PlotStack templates."""
import datetime as dt
from PyQt4.QtGui import *
import pyqtgraph as gr

import plots
import system.navalasystem as na
from system import configs as con
from misc import misc
import plottemplates
import misc.quoteperiod as qp
#TODO I may need to sort my problem with the ViewBox thing

class ScreenSet(object):
    """Manages a QGridLayout and data.
    
    This class renders a QGridLayout and takes care of loading/updating
    stock data."""
    # (=1) Column count
    numCols = 1
    # Slot for PostCrosshairTuples signals
    crosshairTuplesSlot = None
    # Name of Screen Set
    name = "(unnamed)"
    
    # List of Screen objects
    _screens = None
    @property
    def screens(self):
        return self._screens
    
    def __init__(self):
        self._screens = []
        self._grids = None # PlotGrid objects

    def AddScreens(self, a):
        """a -- list of Screen objects."""
        for screen in a:
            self.AddScreen(screen)

    def AddScreen(self, x):
        """a -- list of Screen objects."""
        self._screens.append(x)
        
    def RenderLayout(self, parent):
        """Renders a QGridLayout. This can be called only once.
        
        parent -- QWidget that can be used as 
        """
        lay = QGridLayout(parent)
        lay.setContentsMargins(0, 0, 0, 0)
        
        row, col = 0, 0
        self._grids = []
        for screen in self._screens:
            p = screen.GetPlotGrid() # grid although with 1 plot only
            if self.crosshairTuplesSlot is not None:
                p.PostCrosshairTuples.connect(self.crosshairTuplesSlot)
            
            # Creates and adds GraphicsView to layout
            gv = gr.GraphicsView()
            lay.addWidget(gv, row, col)
            gv.setCentralItem(p)
            self._grids.append(p)
            if col == self.numCols-1:
                col, row = 0, row+1
            else:
                col += 1
        
        self._layout = lay
        
    def SetStockName(self, s):
        """Reads datasets and assigns to respective grids."""
        if self._grids is None:
            raise RuntimeError("Call RenderLayout() first!")
        for (i, screen) in enumerate(self._screens):
            d = screen.GetData(s)
            self._grids[i].SetTimeData([d])
            self._grids[i].Update()
        


    def SetupFromSection(self, section):
        """Reads screens information from configobj.Section object.
        
        Arguments:
            section -- configobj.Section object, see w_stockscreens.py
            
        This routine must be called only once within self's lifecycle."""
        for (key, conf) in section.iteritems(): # dict may not be sorted, we'll
                                                 # see what happens
            if key == "numCols":
                self.numCols = eval(conf)
            else:
                obj = Screen()
                obj.name = key # Assumes without verification that the current
                               # entry is a subsection and uses the subsection
                               # name as the screen set name
                if conf.has_key("numPoints"):
                    obj.numPoints = eval(conf["numPoints"])
                obj.initialDt = misc.str2dt(conf["initialDt"])
                s_period = conf["period"]
                if s_period.isdigit():
                    obj.period = eval(s_period)
                else:
                    obj.period = qp.FindPeriod(s_period)
                        
                obj.flagFinishNow = eval(conf["flagFinishNow"])
                if not obj.flagFinishNow:
                    obj.finishDt = misc.str2dt(conf["finishDt"])
                if conf.has_key("stackClass"):
                    obj.stackClass = \
                        eval("plottemplates.%s" % conf["stackClass"])
                else:
                    obj.stackClass = plottemplates.CandleVolume #default
                if conf.has_key("title"):
                    obj.title = conf["title"]
                else:
                    obj.title = "Period: "+qp.data[obj.period]["english"]
                self.AddScreen(obj)


###    def ReadConfig(self, sectionName="screens"):
###        """Reads screens information from config file.
###        
###        This routine must be called only once."""
###        confDict = con.fig.GetRaw(sectionName)
###        for (key, conf) in confDict.iteritems(): # dict may not be sorted, we'll
###                                                 # see what happens
###            if key == "numCols":
###                self.numCols = eval(conf)
###            else:
###                obj = Screen()
###                if conf.has_key("numPoints"):
###                    obj.numPoints = eval(conf["numPoints"])
###                obj.initialDt = misc.str2dt(conf["initialDt"])
###                s_period = conf["period"]
###                if s_period.isdigit():
###                    obj.period = eval(s_period)
###                else:
###                    obj.period = qp.FindPeriod(s_period)
###                        
###                obj.flagFinishNow = eval(conf["flagFinishNow"])
###                if not obj.flagFinishNow:
###                    obj.finishDt = misc.str2dt(conf["finishDt"])
###                if conf.has_key("stackClass"):
###                    obj.stackClass = \
###                        eval("plottemplates.%s" % conf["stackClass"])
###                else:
###                    obj.stackClass = plottemplates.CandleVolume #default
###                if conf.has_key("title"):
###                    obj.title = conf["title"]
###                else:
###                    obj.title = "Period: "+qp.data[obj.period]["english"]
###                self.AddScreen(obj)

    def HideCrosshairs(self):
        for grid in self._grids:
            grid.HideCrosshair()
    

class Screen(object):
    """Non-visual class, PlotGrid generator, data management."""
    ## Setup
    # PlotStack CLASS, not object
    stackClass = None
    # (Optional) Screen title
    title = None
    # quoteperiod.daily etc
    period = None
    # finish datetime
    _finishDt = None
    # whether to use datetime.datetime.now() as finish datetime
    flagFinishNow = True
    # number of points, has preferrence over initialDt, if specified
    numPoints = None
    
    # start datetime
    _initialDt = None
    @property
    def initialDt(self):
        return self._initialDt
    @initialDt.setter
    def initialDt(self, value):
        self._initialDt = value
        
    # finish datetime
    _finishDt = None
    @property
    def finishDt(self):
        return misc.EndOfToday() if self.flagFinishNow else self._finishDt
    @finishDt.setter
    def finishDt(self, value):
        self._finishDt = value
    
    
###    def __init__(self, screenSet):
###        self._screenSet = screenSet
    
    def GetPlotGrid(self):
        p = plots.PlotGrid()
        p.period = self.period
        # TODO this would be better done in the ScreenSet itself, don't need this crosshairtuplesslot property , or maybe it is a property from the screens p.PostCrosshairTuples.connect(self.crosshairTuplesSlot)
        p.SetNumStacks(1)
        self.stackClass(p, self.title)
        return p

#    def GetStartDt(self):
#        return self._initialDt
#
#    def GetFinishDt(self):
#        return dt.datetime.now() if self.flagFinishNow else self._finishDt
        
    def GetData(self, stockName):
        """Asks the Store for data."""
        return na.vala.store.GetQuotes(self.period, stockName,\
            self.initialDt, self.finishDt, self.numPoints)

